#include "audio_task.h"
#include "asr.h"
//#include "fake_data.h"
#include "wm_mem.h"

#include "audio.h"
#include "pvmp3_dec.h"
#include "dev_ringbuf.h"
#include "../user_config.h"

#if USE_PSRAM_AUDIO
#define MEM_MALLOC  dram_heap_malloc
#define MEM_FREE    dram_heap_free
#else
#define MEM_MALLOC  tls_mem_alloc
#define MEM_FREE    tls_mem_free
#endif

#define N 480
//static uint16_t PcmBuf1[N] = {0};
uint16_t *PcmBuf1 = NULL;
#define DEBUG_MEM_FTR 0
#if DEBUG_MEM_FTR
#define USER_DBG_PRT printf
#else
#define USER_DBG_PRT
#endif

#define TASK_PRIOR_MAIN					40
#define TASK_STACK_MAIN					512

#define QUEUE_SIZE_MAIN					8
static tls_os_queue_t *UserMainQueue;
#define MSG_QUEUE_PLAYSOUND 0
#define MSG_QUEUE_RECORD_AND_IDENITFY 1
#define MSG_QUEUE_NO_MSG 2

struct tls_audio_msg
{
	u32 msgno;
	u32 audiono;
};

#define VOICE_STARTUP 1
#define VOICE_WAKEUP 2
#define VOICE_SLEEP 3
#define VOICE_PLUGON 4
#define VOICE_PLUGOFF 5
#define VOICE_SMARTCONFIG 6
#define VOICE_NETCONNET 7

static OS_STK UserMainTaskStk[TASK_STACK_MAIN];
//static OS_STK *UserMainTaskStk = NULL;
#if DEBUG_MP3_PLAY_FOR_AUDIO
static void UserMainTaskProc_mp3(void *param);
#endif
static void UserMainTaskProc(void *param);
static void UserIOInit(void);
//static uint32_t Stereo2Mono(void *audio_buf, uint32_t len, int LR);
u32 startVoiceTask = 1;
static tls_os_timer_t *asrdowntimer = NULL;
static u32 asrwakecount = 0;
static u32 lastasrwakecount = 0;
extern unsigned char ars_get_wakeup_flag(void);
extern void ars_set_wakeup_flag(unsigned char flag);
extern int asr_deal(int item);



void AsrDownTim(void *ptimer, void *parg)
{
	if (lastasrwakecount == asrwakecount)
	{
		// if (ars_get_wakeup_flag())
		// {
			tls_audio_msg_send(MSG_QUEUE_PLAYSOUND, 1);
			// ars_set_wakeup_flag(0);
			// Wanson_ASR_Reset(0);
		// }
	}
	else
	{
		tls_os_timer_change(asrdowntimer, 10 * HZ);
	}
	lastasrwakecount = asrwakecount;
}

void wakeup_timer_clear()
{
	asrwakecount++;
	// tls_os_timer_change(asrdowntimer, 1 * HZ / 500);
	tls_os_timer_change(asrdowntimer, 10 * HZ);
}

void VoiceUserMain(void)
{
	// wm_printf("//user task hz:%d\r\n", tls_mem_get_avail_heapsize());

	if (startVoiceTask)
	{
		if (UserMainQueue == NULL)
		{
			tls_os_queue_create(&UserMainQueue, QUEUE_SIZE_MAIN);
			//UserMainTaskStk = MEM_MALLOC(sizeof(u32)*TASK_STACK_MAIN);
			//if (UserMainTaskStk)
			{
#if DEBUG_MP3_PLAY_FOR_AUDIO
				tls_os_task_create(NULL, "audio", UserMainTaskProc_mp3, NULL,
								   (void *)UserMainTaskStk,
								   TASK_STACK_MAIN * sizeof(u32),
								   TASK_PRIOR_MAIN,
								   0);
#else
				tls_os_task_create(NULL, "audio", UserMainTaskProc, NULL,
								   (void *)UserMainTaskStk,
								   TASK_STACK_MAIN * sizeof(u32),
								   TASK_PRIOR_MAIN,
								   0);
#endif
			}
		}
		else
		{
		}
	}
}

/**
 * \brief  
 * \param[null]
 */
void tls_audio_msg_send(u32 msgno, u32 audiono)
{

	struct tls_audio_msg *audio_msg;
	if (UserMainQueue)
	{
		audio_msg = MEM_MALLOC(sizeof(struct tls_audio_msg));
		if (audio_msg)
		{
			audio_msg->msgno = msgno;
			audio_msg->audiono = audiono;
			tls_os_queue_send(UserMainQueue, (void *)audio_msg, 0);
		}
	}
}
void readme_play(u32 audiono)
{
	tls_audio_msg_send(MSG_QUEUE_PLAYSOUND, audiono);
}
#define DEBUG_DATA_SAVE_PRT 0
#define DEBUG_SAVE_DATA_TO_FLASH 0
#if DEBUG_DATA_SAVE_PRT
#if DEBUG_SAVE_DATA_TO_FLASH
#define FLS_SAVE_START_ADDR (0x8130000)
#define DEBUG_SAVE_DATA_TO_FLASH_SIZE (256 * 1024)
u8 rdflsbuf[4096];
#define STORE_MAX_LEN (32 * 1024)
#else
#define STORE_MAX_LEN (60 * 1024)
#endif
u8 storebuffer[STORE_MAX_LEN];
u32 storebuflen = 0;
#endif
#if USE_WAV_FILE_AS_PLAY_FTR

// int VoiceASRInit(void)
// {
// 	if (PcmBuf1 == NULL)
// 	{
// 		if (Wanson_ASR_Init() < 0)
// 		{
// 			printf("//Wanson_ASR_Init Failed!\n");
// 			return -1;
// 		}
// 		Wanson_ASR_Reset(1);			
// 		PcmBuf1 = (uint16_t *)MEM_MALLOC(N * 2);
// 		if (PcmBuf1 == NULL)
// 		{
// 			USER_DBG_PRT("PcmBuf1 allocated Failed!\n");
// 			return -2;
// 		}
// 	}

// 	return 0;
// }

static void UserMainTaskProc(void *param)
{
	int rs = 0;
	const char *text;
	int score;
	int energ;
	int id = 0;
//	int t1 = 0, t2 = 0;
//	int t = 0;
	int len = 0;
//	int i = 0;
//	int j = 0;
//	int k = 0;
//	u32 value = 0;
	struct tls_audio_msg *msg = NULL;
	u32 msgno = 0;
	u32 audiono = 0;
	int ret = 0;
#if DEBUG_SAVE_DATA_TO_FLASH
	int startsavepos = 0;
	/*Erase data area for audio record save*/
	//wm_printf("//Erase Save Area");
	for (i = 0; i < DEBUG_SAVE_DATA_TO_FLASH_SIZE; i += 4096)
	{
		tls_fls_erase((FLS_SAVE_START_ADDR + i) / 4096);
	}
	//wm_printf("//Erase Save OK");
#endif

	// printf("**********************************************************************************************************\n");
	// tls_gpio_cfg(WM_IO_PB_05, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
	// tls_gpio_write(WM_IO_PB_05, 0);

	//printf("//Wanson_ASR_Init OK!\r\n");
#if DEBUG_DATA_SAVE_PRT

#else
	// tls_os_timer_create(&asrdowntimer, AsrDownTim, NULL, 3 * HZ, FALSE, NULL);
	// if (asrdowntimer)
	// {
	// 	tls_os_timer_change(asrdowntimer, 10 * HZ);
	// }
#endif

	UserIOInit();

	AudioInit(4 * AUDIO_BUF_SIZE);

#if DEBUG_DATA_SAVE_PRT
	ret = VoiceASRInit();
	if (0 == ret)
	{
		RecordFifoInit(4 * AUDIO_BUF_SIZE);	
		RecordStart(16000, 16);
		tls_os_time_delay(2);
		tls_audio_msg_send(MSG_QUEUE_RECORD_AND_IDENITFY, 0xFFFF);
	}
#endif

	for (;;)
	{
		ret = tls_os_queue_receive(UserMainQueue, (void **)&msg, 0, 0);
		if (msg)
		{
			msgno = (u32)msg->msgno;
			audiono = msg->audiono;
			MEM_FREE(msg);
		}
		else
		{
			msgno = MSG_QUEUE_NO_MSG;
		}
		switch (msgno)
		{
		case MSG_QUEUE_PLAYSOUND:
		{
			RecordStop();
			RecordFifoDeInit();

			wm_printf("---> msg->audiono:%d\r\n", audiono);
#if USE_MP3_FOR_AUDIO
			ad_pvmp3_open();
#endif
			PlayDataSet(audiono);
			PlayStart(16000, 16);
#if USE_MP3_FOR_AUDIO
			audio_mp3_decode();
#endif
			/*Stop Play & Restart Record*/
			PlayStop();
#if USE_MP3_FOR_AUDIO
			ad_pvmp3_close();
#endif
			
#if !CODEC_ALWAYS_AS_MASTER_FTR
			CodecReInit();
#endif
			if (audiono == 6)
			{
				printf("audio reset\r\n");
				tls_sys_reset();
			}

			// ret = VoiceASRInit();
			// if (0 == ret)
			// {
			// 	RecordFifoInit(4 * AUDIO_BUF_SIZE);			
			// 	RecordStart(16000, 16);
			// 	tls_os_time_delay(1);
			// 	tls_audio_msg_send(MSG_QUEUE_RECORD_AND_IDENITFY, 0xFFFF);
			// }
		}
		break;

		case MSG_QUEUE_RECORD_AND_IDENITFY:
		{
			len = FifoDataLen();
			ret = -1;
			do
			{
				if (len >= (N * 2))
				{
					len -= N * 2;
					FifoRead((uint8_t *)PcmBuf1, N * 2);
					rs = 0;
#if DEBUG_SAVE_DATA_TO_FLASH
					memcpy(&storebuffer[storebuflen], PcmBuf1, N * 2);
					storebuflen += N * 2;
#endif

					//if (i != N)
					{ 
						//t1 = tls_os_get_time();
						// tls_gpio_write(WM_IO_PB_05, 1);
						// rs = Wanson_ASR_Recog((short *)PcmBuf1, N, &text, &score, &energ, &id);
						// tls_gpio_write(WM_IO_PB_05, 0);
						//t2 = tls_os_get_time();
						// wm_printf("t:%d(ms)\r\n", (t2 - t1) * 2);
					}

					if (rs == 1)
					{
						wm_printf("\n//ASR Result: %s\r\n", text);
						// ret = asr_deal(id);
#if DEBUG_DATA_SAVE_PRT
						wm_printf("//ret:%d\r\n", ret);
#else
						if (ret >= 0)
						{
							// tls_audio_msg_send(MSG_QUEUE_PLAYSOUND, ret);
							// if (asrdowntimer)
							// {
							// 	if (ret == 2)
							// 	{
							// 		tls_os_timer_change(asrdowntimer, 1 * HZ / 500);
							// 	}
							// 	else
							// 	{
							// 		tls_os_timer_change(asrdowntimer, 10 * HZ);
							// 	}
							// }

							break;
						}
#endif
					}
				}
			} while (len >= N * 2);

#if DEBUG_DATA_SAVE_PRT
#if DEBUG_SAVE_DATA_TO_FLASH
			//wm_printf("//len:%d\r\n", storebuflen);
			if (storebuflen >= 8192)
			{
				tls_fls_write(FLS_SAVE_START_ADDR + startsavepos, storebuffer, 8192);
				startsavepos += 8192;
				if (storebuflen - 8192 > 0)
				{
					memcpy(&storebuffer[0], &PcmBuf1[storebuflen - 8192], storebuflen - 8192);
					storebuflen = storebuflen - 8192;
				}
				else
				{
					storebuflen = 0;
				}
				if (startsavepos >= DEBUG_SAVE_DATA_TO_FLASH_SIZE)
				{
					RecordStop();
					// wm_printf("char data_%d[]={",j);
					wm_printf("\r\n\r\n");
					j++;
					for (i = FLS_SAVE_START_ADDR; i < (FLS_SAVE_START_ADDR + DEBUG_SAVE_DATA_TO_FLASH_SIZE); i += 4096)
					{
						tls_fls_read(i, &rdflsbuf[0], 4096);
						for (k = 0; k < 4096; k++)
						{
							printf("0x%02x,", (char)rdflsbuf[k]);
							if ((k + 1) % 16 == 0)
							{
								printf("\n");
							}
						}
					}
					//wm_printf("};\n");
					storebuflen = 0;
					startsavepos = 0;
#if 0						
							/*Erase data area for audio record save*/
							wm_printf("//Erase Save Area");
							for (i = 0; i < DEBUG_SAVE_DATA_TO_FLASH_SIZE; i += 4096)
							{
								tls_fls_erase((0x8130000+i)/4096);
							}
							wm_printf("//Erase Save OK");
							tls_os_time_delay(1);
							RecordStart(16000, 16); 
							tls_audio_msg_send(MSG_QUEUE_RECORD_AND_IDENITFY,0xFFFF);
#endif
				}
				else
				{
					tls_audio_msg_send(MSG_QUEUE_RECORD_AND_IDENITFY, 0xFFFF);
				}
			}
#else
			if ((storebuflen + N * 2) <= STORE_MAX_LEN)
			{
				memcpy(&storebuffer[storebuflen], PcmBuf1, N * 2);
			}
			storebuflen += N * 2;

			if (storebuflen >= STORE_MAX_LEN)
			{
				RecordStop();
				wm_printf("//rs:%d,%d\r\n", rs, t2 - t1);
				wm_printf("char data_%d[]={", j);
				j++;
				for (i = 0; i < storebuflen; i++)
				{
					wm_printf("0x%x,", storebuffer[i]);
				}
				wm_printf("};\n");
				storebuflen = 0;
				tls_os_time_delay(1);
				RecordStart(16000, 16);
				tls_audio_msg_send(MSG_QUEUE_RECORD_AND_IDENITFY, 0xFFFF);
			}
#endif
			else
			{
				tls_os_time_delay(2);
				tls_audio_msg_send(MSG_QUEUE_RECORD_AND_IDENITFY, 0xFFFF);
			}
#else
			if (ret < 0)
			{
				tls_os_time_delay(1);
				tls_audio_msg_send(MSG_QUEUE_RECORD_AND_IDENITFY, 0xFFFF);
			}
#endif
		}
		break;
		default:
			break;
		}
	}
}
#endif

#if USE_RECORD_DATA_AS_PLAY_FTR
u32 bufprt[1024];

static void UserMainTaskProc(void *param)
{
	int t1 = 0;
	int j = 0;
	u32 len = 0;

	
#define RECORD_DATA_LEN (100 * 1024)
	UserIOInit();
	AudioInit(RECORD_DATA_LEN);
	wm_printf("start record & play\r\n");
	RecordStart(16000, 16);
	tls_os_time_delay(500);
	RecordStop();

	len = FifoDataLen();
//	printf("len:%d\r\n", len);
	while (len && (len >= 512*2))
	{
		FifoRead((uint8_t *)bufprt, 512 * 2);	
		int16_t *pBf= (int16_t *)bufprt;
		for(int j=0; j<512; j++)
		{
			if(j%32==0)
			printf("\n");
			printf("%d ",pBf[j]);
		}
		len -= 512*2;
	}
	printf("\n");


	while (1)
	{
		tls_os_time_delay(1024);
	}
}
#endif

#if DEBUG_MP3_PLAY_FOR_AUDIO
static void UserMainTaskProc_mp3(void *param)
{
	// wm_printf("init00\r\n");

	UserIOInit();
	AudioInit(4 * AUDIO_BUF_SIZE);
	RecordStop();
#if USE_MP3_FOR_AUDIO
	ad_pvmp3_open();
#endif
	PlayDataSet(1);
	PlayStart(16000, 16);
	// wm_printf("init33\r\n");
#if USE_MP3_FOR_AUDIO
	audio_mp3_decode();
#endif
	/*Stop Play & Restart Record*/
	PlayStop();
#if USE_MP3_FOR_AUDIO
	ad_pvmp3_close();
    printf("---> end\n");
#endif
	while (1)
	{
		tls_os_time_delay(1024);
	}
}
#endif

static void UserIOInit(void)
{
	// PA
	tls_gpio_cfg(USER_PA_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
	tls_gpio_write(USER_PA_PIN, 0);
}

void UserPACtrl(uint8_t flag)
{
	tls_gpio_write(USER_PA_PIN, flag);
}
